﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BrokerBase.Lib.Product;
using System.Xml.Linq;
using BrokerBase.Lib.Policy;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;
using System.Resources;
using BrokerBase.Lib.Product.RateFactorConverter;
using BrokerBase.Lib.Product.AdjustRateConverter;
using System.Runtime.InteropServices;
using System.Data.OleDb;
using System.Data;

namespace BrokerBase.Lib.Tool
{
    public static class ProductUtil
    {
        public const string DUTY_TEMPLATE_FILE_NAME = "DutyTempate.xml";

        public const string AUXPROPERTY_TEMPLATE_FILE_NAME = "AuxPropertyTemplate.xml";

        public const string EXPANDEXPRESS_TEMPLATE_FILE_NAME = "ProductExpanderCode.xml";

        public static IList<IDuty> LoadDutyTemplate()
        {
            IList<IDuty> duties = new List<IDuty>();

            XElement root = XElement.Load(DUTY_TEMPLATE_FILE_NAME);

            IEnumerable<XElement> temps = root.Elements("Template");

            XElement states = null;

            foreach (XElement el in temps)
            {
                IDuty duty = new Duty();

                duty.Name = el.Attribute("Name").Value;

                states = el.Element("InsurantStates");

                if (states != null && !states.IsEmpty)
                    duty.InsurantStates = states.Value;

                states = el.Element("HolderStates");

                if (states != null && !states.IsEmpty)
                    duty.HolderStates = states.Value;

                duty.Description = el.Element("Description").Value;
                duty.Code = el.Element("Code").Value;

                duties.Add(duty);
            }


            return duties;
        }


        public static IList<IAuxProperty> LoadAuxPropertyTemplates()
        {
            IList<IAuxProperty> temps = new List<IAuxProperty>();

            XElement root = XElement.Load(AUXPROPERTY_TEMPLATE_FILE_NAME);

            IEnumerable<XElement> elements = root.Elements("Template");

            foreach (XElement el in elements)
            {
                IAuxProperty aux = new AuxProperty();

                aux.Name = el.Attribute("Name").Value;
                aux.DataType = el.Attribute("Type").Value;
                aux.Value = el.Attribute("Value").Value;
                aux.IsVariable = bool.Parse(el.Attribute("IsIsVariable").Value);
                aux.Description = el.Attribute("Description").Value;


                temps.Add(aux);

            }

            return temps;
        }

        public static string LoadExpandExpressTemplate()
        {
            IList<IDuty> duties = new List<IDuty>();

            XElement root = XElement.Load(EXPANDEXPRESS_TEMPLATE_FILE_NAME);

            IEnumerable<XElement> temps = root.Elements("Templates");

            XElement tmp=root.Element("Code");

            string code = tmp.Value;

            return code;
        }

        public static IList<Action<IPolicyPeriodActing, IDutyActing>> CreateDutyAction(IList<IDuty> duties,out bool succes,out string info)
        {

            info = string.Empty;
            succes = false;

            try
            {
                string[] classNames = new string[duties.Count];

                IList<Action<IPolicyPeriodActing, IDutyActing>> ls = new List<Action<IPolicyPeriodActing, IDutyActing>>();

                CSharpCodeProvider provider = new CSharpCodeProvider();

                CompilerParameters par = new CompilerParameters();

                par.ReferencedAssemblies.Add("System.dll");
                par.ReferencedAssemblies.Add("System.Core.dll");
                par.ReferencedAssemblies.Add("mscorlib.dll");
                par.ReferencedAssemblies.Add("BrokerBase.Lib.dll");

                par.GenerateExecutable = false;
                par.GenerateInMemory = true;

                Assembly assembly;
                ResourceManager rmManager;

                assembly = Assembly.GetExecutingAssembly();
                rmManager = new ResourceManager("BrokerBase.Lib.TextResource", assembly);
                string s = rmManager.GetString("UsingCode");

                StringBuilder code = new StringBuilder(1000);

                code.Append(s);
                code.Append(Environment.NewLine);

                code.Append("namespace BrokerBase.Lib.Product");
                code.Append(Environment.NewLine);
                code.Append("{");
                code.Append(Environment.NewLine);

                for(int i=0;i<duties.Count;i++)
                {
                    classNames[i] = "D" + i;//class 名称
                    string classCode=CreateClassCode(duties[i],classNames[i]);

                    code.Append(Environment.NewLine);
                    code.Append(classCode);
                    code.Append(Environment.NewLine);

                    string ss = code.ToString();
                }
                code.Append("}");

                string module = code.ToString();

                CompilerResults compile = provider.CompileAssemblyFromSource(par, new string[] { module });

                if (compile.Errors.HasErrors)
                {
                    info="编译失败";
                    foreach (CompilerError e in compile.Errors)
                    {

                        info += Environment.NewLine + e.ErrorText;
                        Console.WriteLine(e.ErrorText);
                    }
                }
                else
                {
                    info = "编译成功!";
                    succes = true;

                    Assembly dyAssembly = compile.CompiledAssembly;
                    for (int i=0;i<classNames.Count();i++)
                    {
                        string className = classNames[i];
                        IDutyAction da = (IDutyAction)dyAssembly.CreateInstance("BrokerBase.Lib.Product." + className);
                        duties[i].Action = da.Calc;
                        ls.Add(da.Calc);
                    }
                }

                return ls;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public static IRateFactorConverter GetRateFactorConverter(string  rfName)
        {
            IRateFactorConverter rfc = null;

            rfc = new PaymentPeriodConverter();
            if (rfc.IsMatch(rfName))
            {
                return rfc;
            }


            rfc = new InsurancePeriodConverter();
            if (rfc.IsMatch(rfName))
            {
                return rfc;
            }

            rfc = new SexConverter();
            if(rfc.IsMatch(rfName))
            {
                return rfc;
            }

            rfc = new BasicAmountConverter();
            if (rfc.IsMatch(rfName))
            {
                return rfc;
            }

            rfc = new AgeConverter();
            if (rfc.IsMatch(rfName))
            {
                return rfc;
            }

            rfc = new HoldAgeConverter();

            if (rfc.IsMatch(rfName))
            {
                return rfc;
            }

            return null;
        }


        public static IList<IAdjustRateConverter> GetAdjConverters()
        {
            IList<IAdjustRateConverter> adjs = new List<IAdjustRateConverter>();

            TimeUnitAdjConverter tAdj = new TimeUnitAdjConverter();

            adjs.Add(tAdj);

            return adjs;
        }

        private static string CreateClassCode(IDuty duty,string className)
        {
            StringBuilder code = new StringBuilder(500);

            code.Append("   public class " + className + ":IDutyAction");
            code.Append(Environment.NewLine);
            code.Append("   {");
            code.Append(Environment.NewLine);
            code.Append("       public void Calc(IPolicyPeriodActing ppa,IDutyActing da)");
            code.Append(Environment.NewLine);
            code.Append("           {");
            code.Append(Environment.NewLine);
            code.Append(duty.Code);
            code.Append("           }");
            code.Append(Environment.NewLine);
            code.Append("   }");

            return code.ToString();
        }

        public static IList<IAdjustRateConverter> GetAdjustRateConverters()
        {
            IList<IAdjustRateConverter> ls = new List<IAdjustRateConverter>();

            IAdjustRateConverter adj1 = new TimeUnitAdjConverter();

            ls.Add(adj1);


            return ls;
            
        }

        public static IList<string> GetFixRateFactorCombKeys(IProduct product)
        {


            IList<string> ls = new List<string>();
                
            for (int i = 0; i < product.ColRateFactors.Count; i++)
            {
                string[] s = product.ColRateFactors[i].Items.Split(';');

                for (int j = 0; j < s.Count(); j++)
                {
                    if(!string.IsNullOrEmpty(s[j]))
                    {
                        ls[j] += ls[j] == null ? s[j] : "-" + s[j];
                    }
                }
            }

            return ls;
        }


    }
}
